﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using EventPlanner.Models;
using System.Net.Mail;
using System.Net;
using EventPlanner.Servicios;


namespace EventPlanner.Controllers
{        
    /* Controlador de eventos */
    public class EventoController : Controller
    {        
        IDbContext db;

        /*Constructor sin parámetros: crea una instancia de la clase a partir de la base de datos real de EventPlanner */
        public EventoController()
        {
            db = new EventPlannerDB();            
        }

        /*Constructor con un parámetro: crea una instancia de la clase a partir de una base de datos simulada como parámetro */
        public EventoController(IDbContext fake_db)
        {
            db = fake_db;
        }


        /* Devuelve una lista del tipo SelectList con los diferentes tipos de entrada  */
        private SelectList GenerarListaDeEntradas()
        {
            var entradas = new List<string>();
            entradas.Add("Sin Costo");
            entradas.Add("Con Costo");
            entradas.Add("Promocional");
            entradas.Add("Con costo VIP");

            return (new SelectList(entradas));
        }


        /*GET - Muestra la lista de eventos totales en el sistema */
        public ActionResult Index()
        {                        
            var model = db.Eventos;
            return View(model);
        }

        /*GET - Muestra la lista de eventos pertenecientes al usuario actualmente logueado */
        [Authorize]
        public ActionResult MisEventos()
        {            
            var usuario = UsuarioActual();

            if (usuario == null)            {
                Elmah.ErrorSignal.FromCurrentContext().Raise(new System.NullReferenceException("El usuario no puede ser nulo"));
                return (RedirectToAction("ErrorAmigable", "Excepcion", new { NumError = 1 }));
            }
            var model = usuario.EventosCreados;
            return View(model);
        }

        
        /*GET - Muestra los detalles de un evento para parámetro de entrada */
        public ActionResult Details(int id)
        {            
            var evento = db.Find<Evento>(id);

            if (evento == null){
                Elmah.ErrorSignal.FromCurrentContext().Raise(new System.NullReferenceException("El evento no puede ser nulo"));
                return (RedirectToAction("ErrorAmigable", "Excepcion", new { NumError = 3 }));
            }
            return View(evento);
            
            
        }


        /*GET - Crea un nuevo evento */
        public ActionResult Create()
        {
            ViewData["entradas"] = GenerarListaDeEntradas();
            return View();
        }


        /*POST - Crea un nuevo evento */
        [HttpPost]
        public ActionResult Create(Evento NuevoEvento, string entradas)
        {
            NuevoEvento.TipoDeEntrada = entradas;
            try
            {
                db.Add<Evento>(NuevoEvento);                
                var usuario = UsuarioActual();
                usuario.EventosCreados.Add(NuevoEvento);                                
                db.SaveChanges();
                return RedirectToAction("MisEventos");
            }
            catch (System.NullReferenceException e)
            {
                Elmah.ErrorSignal.FromCurrentContext().Raise(e);
                return (RedirectToAction("ErrorAmigable", "Excepcion", new { NumError = 1 }));                
            }
            catch (System.Exception e)
            {
                Elmah.ErrorSignal.FromCurrentContext().Raise(e);
                return (RedirectToAction("ErrorAmigable", "Excepcion", new { NumError = 6 }));                
            }
        }


        /*GET - Muestra la vista de edición de un evento ingresado como parámetro de entrada */
        [Authorize]
        public ActionResult Edit(int id)
        {
            ViewData["entradas"] = GenerarListaDeEntradas();
            var evento = db.Find<Evento>(id);

            if (evento == null){
                Elmah.ErrorSignal.FromCurrentContext().Raise(new System.NullReferenceException("El evento no puede ser nulo"));
                return (RedirectToAction("ErrorAmigable", "Excepcion", new { NumError = 3 }));
            }
            return View(evento);
            
        }


        /*POST - Muestra la vista de edición de un evento ingresado como parámetro de entrada */
        [HttpPost]
        [Authorize]
        public ActionResult Edit(int id, string entradas)
        {
            var evento = db.Find<Evento>(id);

            evento.TipoDeEntrada = entradas;

            if (evento == null){
                Elmah.ErrorSignal.FromCurrentContext().Raise(new System.NullReferenceException("El evento no puede ser nulo"));
                return (RedirectToAction("ErrorAmigable", "Excepcion", new { NumError = 3 }));
            }
            else
            {
                if (TryUpdateModel(evento))
                {
                    db.SaveChanges();
                    return RedirectToAction("Index");
                }
                ViewData["entradas"] = GenerarListaDeEntradas();
                return View(evento);                
            }                            
        }


        /*GET - ELIMINA un evento ingresado como parámetro de entrada */
        public ActionResult Delete(int id)
        {
            var evento = db.Find<Evento>(id);

            if (evento == null){
                Elmah.ErrorSignal.FromCurrentContext().Raise(new System.NullReferenceException("El evento no puede ser nulo"));
                return (RedirectToAction("ErrorAmigable", "Excepcion", new { NumError = 3 }));
            }
            return View(evento);
            
        }
        
        
        /*POST - ELIMINA un evento ingresado como parámetro de entrada */
        [HttpPost]
        public ActionResult Delete(int id, FormCollection collection)
        {
            try
            {
                db.Delete<Evento>(db.Find<Evento>(id));                
                db.SaveChanges();
                return RedirectToAction("MisEventos");
            }
            catch (System.ArgumentNullException)
            {
                return (RedirectToAction("ErrorAmigable", "Excepcion", new { NumError = 3 }));
            }
            catch
            {
                return View();
            }
        }


        /* Muestra los eventos a los que se esta inscripto el usuario actual */
        public ActionResult Inscripciones()
        {
            var usuario = UsuarioActual();

            if (usuario == null){
                Elmah.ErrorSignal.FromCurrentContext().Raise(new System.NullReferenceException("El usuario no puede ser nulo"));
                return (RedirectToAction("ErrorAmigable", "Excepcion", new { NumError = 1 }));
            }
            return View(usuario.EventosInscriptos);            
        }
        



        /*GET - Realiza la inscripción del usuario actual a un evento ingresado como parametro */
        public ActionResult Inscripcion(int id)
        {
            var evento = db.Find<Evento>(id);

            if (evento == null){
                Elmah.ErrorSignal.FromCurrentContext().Raise(new System.NullReferenceException("El evento no puede ser nulo"));
                return (RedirectToAction("ErrorAmigable", "Excepcion", new { NumError = 3 }));
            }
            return View(evento);            
        }

        /*POST - Realiza la inscripción del usuario actual a un evento ingresado como parametro */
        [HttpPost]
        public ActionResult Inscripcion(int id, FormCollection collection)
        {
            var evento = db.Find<Evento>(id);
            var usuario = UsuarioActual();

            if (evento == null) {
                Elmah.ErrorSignal.FromCurrentContext().Raise(new System.NullReferenceException("El evento no puede ser nulo"));
                return (RedirectToAction("ErrorAmigable", "Excepcion", new { NumError = 3 })); 
            }
            if (usuario == null) {
                Elmah.ErrorSignal.FromCurrentContext().Raise(new System.NullReferenceException("El usuario no puede ser nulo"));
                return (RedirectToAction("ErrorAmigable", "Excepcion", new { NumError = 1 })); 
            }
                        
            try
            {
                evento.UsuariosInscriptos.Add(usuario);
                usuario.EventosInscriptos.Add(evento);
                db.SaveChanges();
                return RedirectToAction("Inscripciones");
            }
            catch (System.Exception e)
            {
                Elmah.ErrorSignal.FromCurrentContext().Raise(e);
                return (RedirectToAction("ErrorAmigable", "Excepcion", new { NumError = 5 }));
            }                                        
            

            
        }


        /*GET - Elimina la inscripción del usuario actual a un evento ingresado como parámetro */
        public ActionResult EliminarInscripcion(int id)
        {
            var evento = db.Find<Evento>(id);

            if (evento == null){
                Elmah.ErrorSignal.FromCurrentContext().Raise(new System.NullReferenceException("El evento no puede ser nulo"));
                return (RedirectToAction("ErrorAmigable", "Excepcion", new { NumError = 3 }));
            }
            return View(evento);            

        }


        /*POST - Elimina la inscripción a un evento ingresado como parámetro */
        [HttpPost]
        public ActionResult EliminarInscripcion(int id, FormCollection collection)
        {
            var evento = db.Find<Evento>(id);
            var usuario = UsuarioActual();

            if (evento == null) {
                Elmah.ErrorSignal.FromCurrentContext().Raise(new System.NullReferenceException("El evento no puede ser nulo"));
                return (RedirectToAction("ErrorAmigable", "Excepcion", new { NumError = 3 })); 
            }
            if (usuario == null) {
                Elmah.ErrorSignal.FromCurrentContext().Raise(new System.NullReferenceException("El usuario no puede ser nulo"));
                return (RedirectToAction("ErrorAmigable", "Excepcion", new { NumError = 1 })); 
            }
            
            try
            {
                evento.UsuariosInscriptos.Remove(usuario);
                usuario.EventosInscriptos.Remove(evento);
                db.SaveChanges();
                return RedirectToAction("Inscripciones");
            }
            catch (System.Exception e)
            {
                Elmah.ErrorSignal.FromCurrentContext().Raise(e);
                return (RedirectToAction("ErrorAmigable", "Excepcion", new { NumError = 5 }));
            }
        }




        /*GET - Muestra la vista necesaria para enviar invitaciones a los contactos de un evento
         * ingresado como parámetro de entrada*/         
        [Authorize]
        public ActionResult EnviarInvitaciones(int id)
        {
            var evento = db.Find<Evento>(id);

            if (evento == null){
                Elmah.ErrorSignal.FromCurrentContext().Raise(new System.NullReferenceException("El evento no puede ser nulo"));
                return (RedirectToAction("ErrorAmigable", "Excepcion", new { NumError = 3 }));
            }

            ViewBag.subject = "INVITACION: " + evento.Nombre;
            ViewBag.body = evento.Nombre + "\n" +
                            " organiza: " + evento.NombreOrganizador + "\n" +
                            " Lugar: " + evento.Lugar.calle + " " + evento.Lugar.altura + "\n" +
                            " Inicia: " + evento.Inicio + "\n";

            var usuario = UsuarioActual();
            return View(usuario.Contactos);
        }


        /*POST - Muestra la vista necesaria para enviar invitaciones a los contactos de un evento
         * ingresado como parámetro de entrada*/         
        [HttpPost]
        [Authorize]
        public ActionResult EnviarInvitaciones(int id, string[] selcontactos, string subject, string body)
        {
            var usuario = UsuarioActual();
            if (usuario == null)
            {
                Elmah.ErrorSignal.FromCurrentContext().Raise(new System.NullReferenceException("El usuario no puede ser nulo"));
                return (RedirectToAction("ErrorAmigable", "Excepcion", new { msjerror = "Su cuenta de usuario ya no se registra en nuestra base de datos" }));
            }            

            var miscontactos = usuario.Contactos;

            if (selcontactos == null)
            {                                                
                return View(miscontactos);
            }
            else
            {                
                Correo MiCorreo = new Correo();
                try
                {
                    MiCorreo.EnviarMail(selcontactos, subject, body);                    
                    TempData["notice"] = "Mails enviados satisfactoriamente";
                    return View(miscontactos);
                }
                catch (Exception ex)
                {
                    Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
                    TempData["notice"] = ex.Message;
                    return View(miscontactos);
                }

                
            }

            
        }


        /* Devuelve el usuario actualmete logueado */
        private Usuario UsuarioActual()
        {
            string user = db.GetActualUser();
            var Usuarios = from u in db.Usuarios
                           where u.WebSiteUser == user
                           select u;
            Usuario usuario;
            try
            {
                usuario = Usuarios.First();
                return (usuario);
            }
            catch (System.InvalidOperationException e)
            {
                Elmah.ErrorSignal.FromCurrentContext().Raise(e);
                return (null);
            }
        }

        


    }
}
